package com.glink.manage.ftp;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;


@Component
@Slf4j
public class FTPClientFactory extends BasePooledObjectFactory<SSLSessionReuseFTPSClient> {

    @Resource
    public FtpProperties ftpProperties;

    public synchronized SSLSessionReuseFTPSClient create() throws IOException, InterruptedException {
        SSLSessionReuseFTPSClient sslSessionReuseFTPSClientFtp = new SSLSessionReuseFTPSClient(true);
        if (StringUtils.isEmpty(this.ftpProperties.getHost())) {
            log.error("配置为空");
        }
        try {
            sslSessionReuseFTPSClientFtp.connect(this.ftpProperties.getHost(), this.ftpProperties.getPort());
        } catch (IOException e) {
            Thread.sleep(100L);
            log.error("ftp创建连接失败，再次尝试创建:{}", e.getMessage(), e);
            sslSessionReuseFTPSClientFtp.connect(this.ftpProperties.getHost(), this.ftpProperties.getPort());
        }
        boolean result = sslSessionReuseFTPSClientFtp.login(this.ftpProperties.getUsername(), this.ftpProperties.getPassword());
        int replyCode = sslSessionReuseFTPSClientFtp.getReplyCode();
        if (!FTPReply.isPositiveCompletion(replyCode)) {
            sslSessionReuseFTPSClientFtp.disconnect();
            log.warn("FTPServer refused connection");
            return null;
        }
        if (!result) {
            log.warn("FTPServer refused connection,username is  {}", this.ftpProperties.getUsername());
        }

        sslSessionReuseFTPSClientFtp.setFileTransferMode(this.ftpProperties.getTransferFileType());
        sslSessionReuseFTPSClientFtp.setControlEncoding(this.ftpProperties.getEncoding());
        if (this.ftpProperties.isPassiveMode()) {
            sslSessionReuseFTPSClientFtp.enterLocalPassiveMode();
        } else {
            sslSessionReuseFTPSClientFtp.enterLocalActiveMode();
        }
        sslSessionReuseFTPSClientFtp.execPBSZ(0L);
        sslSessionReuseFTPSClientFtp.execPROT("P");

        sslSessionReuseFTPSClientFtp.setFileType(2);

        sslSessionReuseFTPSClientFtp.setConnectTimeout(60000);

        sslSessionReuseFTPSClientFtp.setBufferSize(this.ftpProperties.getBufferSize());
        FTPClientConfig conf = new FTPClientConfig("UNIX");
        sslSessionReuseFTPSClientFtp.configure(conf);
        return sslSessionReuseFTPSClientFtp;
    }


    public PooledObject<SSLSessionReuseFTPSClient> wrap(SSLSessionReuseFTPSClient sslSessionReuseFTPSClient) {
        return (PooledObject<SSLSessionReuseFTPSClient>) new DefaultPooledObject(sslSessionReuseFTPSClient);
    }

    public void destroyObject(PooledObject<SSLSessionReuseFTPSClient> sslSessionReuseFTPSClient) throws Exception {
        if (sslSessionReuseFTPSClient == null) {
            return;
        }
        SSLSessionReuseFTPSClient objectSSLClient = sslSessionReuseFTPSClient.getObject();

        try {
            if (objectSSLClient != null && objectSSLClient.isConnected()) {
                objectSSLClient.logout();
            }
        } catch (Exception e) {
            log.error("ftp client loginout faild...{}", e);
            throw e;
        } finally {
            if (objectSSLClient != null) {
                objectSSLClient.disconnect();
            }
        }
    }


    public boolean validateObject(PooledObject<SSLSessionReuseFTPSClient> sslSessionReuseFTPSClient) {
        try {
            SSLSessionReuseFTPSClient client = (SSLSessionReuseFTPSClient) sslSessionReuseFTPSClient.getObject();
            return client.sendNoOp();
        } catch (IOException iOException) {


            return false;
        }
    }


    @Nullable
    public SSLSessionReuseFTPSClient createRemoteFTPClient() throws IOException {
        if (StringUtils.isEmpty(this.ftpProperties.getHost())) {
            log.error("未获取到远程系统FTP配置");
            return null;
        }
        SSLSessionReuseFTPSClient client = new SSLSessionReuseFTPSClient(true);
        client.connect(this.ftpProperties.getHost(), this.ftpProperties.getPort());
        boolean result = client.login(this.ftpProperties.getUsername(), this.ftpProperties.getPassword());
        int replyCode = client.getReplyCode();
        if (!FTPReply.isPositiveCompletion(replyCode)) {
            client.disconnect();
            log.error("远程系统{}FTP拒绝连接", this.ftpProperties.getHost());
            return null;
        }
        if (!result) {
            log.error("远程系统{}FTP认证失败", this.ftpProperties.getHost());
            return null;
        }
        client.setFileTransferMode(this.ftpProperties.getTransferFileType());
        client.setConnectTimeout(this.ftpProperties.getConnectTimeout());
        client.execPBSZ(0L);
        client.execPROT("P");
        if (this.ftpProperties.isPassiveMode()) {
            client.enterLocalPassiveMode();
        } else {
            client.enterLocalActiveMode();
        }
        client.setFileType(2);
        client.setBufferSize(this.ftpProperties.getBufferSize());
        client.setControlEncoding(this.ftpProperties.getEncoding());
        FTPClientConfig conf = new FTPClientConfig("UNIX");
        client.configure(conf);
        return client;
    }

    public void disconnect(SSLSessionReuseFTPSClient client) {
        try {
            if (client != null && client.isConnected()) {
                client.logout();
                client.disconnect();
            }
        } catch (IOException e) {
            log.warn("远程系统FTP连接关闭时异常{}", e.getMessage());
        }
    }
}

 